// @author David Alexa <alexa.david@me.com>
//
// Copyright (C) 2012-2015 CESNET
//
// LICENSE TERMS
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with the
//    distribution.
// 3. Neither the name of the Company nor the names of its contributors
//    may be used to endorse or promote products derived from this
//    software without specific prior written permission.
//
// ALTERNATIVELY, provided that this notice is retained in full, this
// product may be distributed under the terms of the GNU General Public
// License (GPL) version 2 or later, in which case the provisions
// of the GPL apply INSTEAD OF those given above.
//
// This software is provided ``as is'', and any express or implied
// warranties, including, but not limited to, the implied warranties of
// merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the company or contributors be liable for any
// direct, indirect, incidental, special, exemplary, or consequential
// damages (including, but not limited to, procurement of substitute
// goods or services; loss of use, data, or profits; or business
// interruption) however caused and on any theory of liability, whether
// in contract, strict liability, or tort (including negligence or
// otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// @link inspired by @link        http://nettephp.com/cs/extras/jquery-ajax

jQuery.extend({
	netopeergui: {

		// replaces content of blocks given in json encoded response
		updateSnippet: function (id, html) {

			// if block singleContent is not available, put content of it into blockState
			if (id === "block--singleContent" && !$("#block--singleContent").length) {
				id = 'block--state';

			// if blockState is not available, put content of it into singleContent
			} else if (id === "block--state" && !$("#block--state").length) {
				id = 'block--singleContent';
			}

			// if blockConfig does not exists, create new one after blockState
			if (id === "block--config" && !$("#block--config").length) {
				var $afterEl;
				if ($("#block--state").length) {
					$afterEl = $("#block--state");
				} else {
					$afterEl = $("#block--singleContent");
				}

				var tmp = $('<section></section>').insertAfter($afterEl);
				tmp.addClass('left-nav-defined')
					.addClass('scrollable-cover')
					.attr('add-data-scrollable', 'true')
					.attr('id', 'block--config')
				;
				$afterEl.attr('id', 'block--state').addClass('left-nav-defined');
			}

			// in dev environment, assets generated by assetic bundle has wrong URL, change it to correct one
			if ((id === "block--moduleJavascripts" || id === "block--moduleStylesheet") && window.location.href.indexOf("app_dev.php") !== -1) {
				html = html.replace('_controller', 'app_dev.php');
			}

			// if we have new alerts, do not replace the content, but append them at the end of alerts block
			if (id === "block--alerts") {
				$("#" + id).append(html);

			// browsers change the syntax of inserted <script> or <link> element by themselves, unify the inserted syntax of this elements
			} else if ((id === "block--moduleJavascripts" || id === "block--moduleStylesheet") && $("#" + id).html().trim() == html.replace(" \/>", ">").trim()) {
				// do not change content of styles or js if did not changed
			} else if (id == 'block--singleContent' && typeof angular !== "undefined") {
				var $blockEl = $("#mainView");

				try {
					angular.element(document).injector().invoke(function($compile) {
						var scope = angular.element(document.querySelector('#mainView')).scope();
						scope.reloadData(false);
					});
				} catch (err) {
					console.error(err);
					$blockEl.html(html);
				}

			// replace content of given block with new html
			} else {
				//console.log(id);
				//console.log($("#" + id).html().trim());
				//console.log(html.replace(" \/>", ">").trim());
				var $blockEl = $("#" + id);
				$blockEl.html(html);
			}

			// if we have modal window, open it and bind necessary actions
			if (id === "block--modalWindow") {
				$("#block--modalWindow").show();
				createFormUnderlay($("#block--modalWindow"));
				bindModalWindowActions();
			}

		},


		// process all data from response given in loadAjaxLink function
		processResponseData: function (payload, callback) {
			// redirect given response if requested
			if (payload.redirect) {
				window.location.href = payload.redirect;
				return;
			}

			// go through all given snippets and modify content of HTML DOM appropriately
			if (payload.snippets) {

				// remove configBlock if we are in merged column layout
				if (!("block--config" in payload.snippets) && payload.treeColumns !== true) {
					$("#block--config").remove();
					$("#block--state").attr('id', 'block--singleContent');
				}

				// toggle class column in sections
				if (("block--config" in payload.snippets) && (("block--state" in payload.snippets) || ("block--singleContent" in payload.snippets))) {
					$("#block--config, #block--singleContent, #block--state").addClass('column');
				} else {
					$("#block--config, #block--singleContent, #block--state").removeClass('column');
				}

				// go through all snippets
				for (var i in payload.snippets) {
					jQuery.netopeergui.updateSnippet(i, payload.snippets[i]);
				}

				// init common JS after block update
				initJS();

				// init module JS if exists
				if (typeof initModuleDefaultJS !== "undefined") {
					initModuleDefaultJS();
				}
			}

			// call given callback if exists
			if (typeof callback !== "undefined") {
				callback();
			}
		},

		// handles ajax response from server
		successAjaxFunction: function(data, textStatus, jqXHR, href, $elem) {
			if ($elem.data().ajaxRedirect) {
				data.redirect = href;
			}

			// push requested URL into history (to enable forward and backward walkthrough)
			if ($elem.data().disableHistory !== true) {
				var historyHref = href;
				if (data.historyHref !== "") {
					historyHref = data.historyHref;
				}
				history.pushState(historyHref, "", historyHref);
			}

			// process given data and hide spinner in success callback
			this.processResponseData(data, function() {
				$.netopeergui.hideSpinner();
			});

			// set clicked link as active
			if ($('a[href="'+ href +'"]').length && $elem.data().disableActiveLink !== true) {
				this.setActiveLink($('a[href="'+ href +'"]'));
			}

			// call callback defined in clicked link (or submitted form)
			if ($elem.data().callback !== undefined) {
				eval($elem.data().callback + ';');
			}
		},

		// loads ajax request to given href, with type (POST, GET...) and with data (request values)
		loadAjaxLink: function(e, $THIS, href, type, data) {
			e.preventDefault();

			// check form modifications
			var shouldLoadingContinue = $.netopeergui.formInputChangeConfirm(true);
			if (!shouldLoadingContinue) {
				return;
			}

			// clear alerts block on every request
			$("#block--alerts").html('');

			$.netopeergui.showSpinner();

			$.ajax({
				url: href,
				dataType: "json",
				data: data,
				type: type,
				success: function(data, textStatus, jqXHR) {
					//if (typeof angular !== "undefined" && $("#mainView").length) {
					//	$("#block--moduleJavascripts, #block--moduleStylesheet").html('');
					//	try {
					//		var scope = angular.element(document).scope();
					//		scope.jsonData = {};
					//		scope.jsonString = "{}";
					//		//console.log(scope);
					//		//scope.$destroy();
					//		$(".jsonView").empty();
					//	} catch (err) {
					//		// scope is not set
					//	}
					//}
					$.netopeergui.successAjaxFunction(data, textStatus, jqXHR, href, $THIS);
				},
				error: function(qXHR, textStatus, errorThrown) {
		//			l(qXHR);
		//			l(textStatus);
		//			l(errorThrown);
					window.location.href = href;
				}
			});
		},

		// create animated spinner
		createSpinner: function()	{
			if (!$('#ajax-spinner').length) {
				return this.spinner = $('<div></div>').attr('id', 'ajax-spinner').appendTo('body').hide();
			} else {
				return this.spinner;
			}
		},

		showSpinner: function() {
			$.netopeergui.spinnerTimer = setTimeout(function() {
				$('#ajax-spinner').fadeIn();
			}, 100);
		},

		hideSpinner: function() {
			setTimeout(function() {
				$('#ajax-spinner').fadeOut();
				clearTimeout(this.spinnerTimer);
			}, 150);
		},

		// if exists modified form element, show confirm box
		formInputChangeConfirm: function(showDialog) {
			if (formInputChanged === true) {
				if ( (showDialog && !confirm(formChangeAlert)) || !showDialog) {
					return false;
				} else {
					formInputChanged = false;
				}
			}
			return true;
		},

		// add class to link
		setActiveLink: function($link) {
			if ($link.data().doNotActivate === true) {
				return;
			}

			$link.parents('nav').find('.active').removeClass('active');
			$link.addClass('active');
		}
	}
});

// register event for poping states from browser history
window.onpopstate = function(o) {
	if (o.state !== null) {
		var href = o.state;
		var $THIS = $("<div></div>");

		if ($('a[href="'+ href +'"]').length) {
			$THIS = $('a[href="'+ href +'"]');
		}

		$("#block--alerts").html('');

		$.netopeergui.showSpinner();

		$.ajax({
			dataType: 'json',
			type: 'post',
			url: href,
			success: function(data, textStatus, jqXHR) {
				$THIS.attr('data-disable-history', "true");
				$.netopeergui.successAjaxFunction(data, textStatus, jqXHR, href, $THIS);
			},
			error: function() {
				window.location.href = href;
			}
		});
	}
};


// register global handlers for ajax walkthrough
jQuery(function($) {
	$.netopeergui.createSpinner();

	$(document).on('click', 'a.ajaxLink', function(e) {
		$.netopeergui.loadAjaxLink(e, $(this), $(this).attr('href'), "GET", '');
	});

	$("section, #block--leftColumn").on('submit', 'form', function(e) {
		if ($(this).data().disableActiveLink == undefined) {
			$(this).attr('data-disable-active-link', true);
		}
		var formAction = $(this).attr('action');
		if (formAction == "") {
			formAction = window.location.href;
		}

		var serializedData = $(this).serialize();
		if ($(this).data('serializeChildren') == true) {
			$(this).find('form').each(function(i,e) {
				serializedData += "&" + $(e).serialize();
			});
		}

		$.netopeergui.loadAjaxLink(e, $(this), formAction, 'POST', serializedData);
	});

	$("body").on('submit', '.modal form', function(e) {
		$(this).attr('data-callback', 'hideAndEmptyModalWindow()');
		$.netopeergui.loadAjaxLink(e, $(this), $(this).attr('action'), 'POST', $(this).serialize());
		
	});
});
